/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package UpAnh;

import Entity.Account;
import Entity.Album;
import Entity.DAL;
import Entity.Imageupload;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Date;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

/**
 *
 * @author Mr Bao
 */
public class Client implements Runnable {

    private Socket socket;
    private OutputStream out;
    private InputStream in;
    private boolean isRunning;
    private DAL d;
    private int userId;
    private List<Album> albums;
    private List<Imageupload> imageuploads;
    private int indexImage;
    private static int ID = -1;

    public Client(Socket socket, DAL d) {
        this.socket = socket;
        this.d = d;
        isRunning = true;
        try {
            in = socket.getInputStream();
            out = socket.getOutputStream();
        } catch (Exception e) {
            e.printStackTrace();
            Close();
        }
        new Thread(this).start();
    }

    private void Close() {
        try {
            in.close();
            out.close();
            socket.close();
            isRunning = false;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void run() {
        while (isRunning) {
            try {
                int lenght = in.available();
                if (lenght > 0) {
                    byte[] data = new byte[lenght];
                    int count = in.read(data);
                    while (count < lenght) {
                        count += in.read(data, count, lenght - count);
                    }
                    String message = new String(data);
                    System.out.println(message);
                    String[] messages = message.split(":");
                    if (messages[0].equals(MessageType.Register)) {
                        Register(messages[1], messages[2]);
                    } else if (messages[0].equals(MessageType.Login)) {
                        Login(messages[1], messages[2]);
                    } else if (messages[0].equals(MessageType.ListAlbum)) {
                        SendListAlbum();
                    } else if (messages[0].equals(MessageType.ListImageName)) {
                        SendListImageName(Integer.parseInt(messages[1]));
                    } else if (messages[0].equals(MessageType.ViewImage)) {
                        SendImage(Integer.parseInt(messages[1]));
                    } else if (messages[0].equals(MessageType.ViewImageNext)) {
                        SendImageNext();
                    } else if (messages[0].equals(MessageType.ViewImagePre)) {
                        SendImagePre();
                    } else if (messages[0].equals(MessageType.NewUpload)) {
                        SendNewUpload();
                    } else if (messages[0].equals(MessageType.Timkiem)) {
                        Timkiem(messages[1]);
                    } else if (messages[0].equals(MessageType.CreateAlbum)) {
                        CreateAlbum(messages[1]);
                    } else if (messages[0].equals(MessageType.UploadImage)) {
                        int n = Integer.parseInt(messages[1]);
                        String formatImage = messages[2];
                        int albumId = Integer.parseInt(messages[3]);
                        byte[] images = new byte[n];
                        int c = in.read(images);
                        while (c < n) {
                            c += in.read(images, c, n - c);
                        }
                        SaveImage(images, formatImage, d, albums.get(albumId), messages[4]);
                    } else if (messages[0].equals(MessageType.DeleteAlbum)) {
                        DeleteAlbum(Integer.parseInt(messages[1]));
                    } else if (message.equals(MessageType.Exit)){
                        isRunning=false;
                        Close();
                    }
                }
                Thread.sleep(200);
            } catch (Exception e) {
                e.printStackTrace();
//                Close();
            }
            System.gc();
        }
    }

    private void CreateAlbum(String albumName) {
        try {
            Album albumNew = new Album();
            albumNew.setName(albumName);
            albumNew.setDateCreate(new Date());
            albumNew.setIsDelete(false);
            albumNew.setUserId(userId);
            d.Insert(albumNew);
        } catch (Exception e) {
            e.printStackTrace();
//            Close();
        }
    }

    private void Timkiem(String name){
        try {
            imageuploads = d.GetImageUploadByName(name);
            String str = MessageType.ListImageName + ":";
            for (int i = 0; i < imageuploads.size(); i++) {
                str += imageuploads.get(i).getName() + ":";
                if (i > 20) {
                    break;
                }
            }
            str += "END";
            out.write(str.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
//            Close();
        }
    }

    private void SendNewUpload() {
        try {
            imageuploads = d.GetNewImageUpload();
            String str = MessageType.ListImageName + ":";
            for (int i = 0; i < imageuploads.size(); i++) {
                str += imageuploads.get(i).getName() + ":";
                if (i > 20) {
                    break;
                }
            }
            str += "END";
            out.write(str.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
//            Close();
        }
    }

    private void Register(String username, String password) {
        SendMessage(MessageType.Register + ":" + d.Register(username, password));
    }

    private void SendMessage(String message) {
        try {
            out.write(message.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
//            Close();
        }
    }

    private void Login(String username, String password) {
        Account account = d.Login(username, password);
        if (account != null) {
            userId = account.getId();
        } else {
            userId = -1;
        }
        SendMessage(MessageType.Login + ":" + userId);
    }

    private void SendListAlbum() {
        try {
            albums = d.GetAllAlbumByUserId(userId);
            String content = MessageType.ListAlbum;
            for (int i = 0; i < albums.size(); i++) {
                content += ":" + albums.get(i).getName();
            }
            content += ":END";
            SendMessage(content);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void SendListImageName(int index) {
        try {
            Album album = albums.get(index);
            imageuploads = d.GetAllImageuploads(album.getId());
            String str = MessageType.ListImageName + ":";
            for (int i = 0; i < imageuploads.size(); i++) {
                str += imageuploads.get(i).getName() + ":";
                if (i > 20) {
                    break;
                }
            }
            str += "END";
            out.write(str.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void SendImage(int index) {
        try {
            Imageupload imageupload = imageuploads.get(index);
            BufferedImage originalImage = ImageIO.read(new File(imageupload.getNameFile()));
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(originalImage, "png", baos);
            baos.flush();
            byte[] imageInByte = baos.toByteArray();
            baos.close();
            String message = MessageType.ViewImage + ":" + imageInByte.length;
            System.out.println(message);
            out.write(message.getBytes());
            Thread.sleep(200);
            out.write(imageInByte);
            indexImage = index;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private void SendImageNext() {
        if (indexImage < imageuploads.size() - 1) {
            SendImage(indexImage + 1);
        } else {
            SendImage(0);
        }
    }

    private void SendImagePre() {
        if (indexImage > 0) {
            SendImage(indexImage - 1);
        } else {
            SendImage(imageuploads.size() - 1);
        }
    }

    private void SaveImage(byte[] images, String formatImage, DAL d, Album album, String nameImage) {
        try {
            if (ID == -1) {
                ID = d.GetID();
            }
            String fileName = "ImagesUpload/" + ID + "." + formatImage;
            Image image = Toolkit.getDefaultToolkit().createImage(images);
            final BufferedImage bufferedImage = ToBufferedImage(image);
            ImageIO.write(bufferedImage, formatImage, new File(fileName));
            Imageupload imageupload = new Imageupload();
            imageupload.setName(nameImage + "." + formatImage);
            imageupload.setNameFile(fileName);
            imageupload.setDateUpload(new Date());
            imageupload.setAlbumId(album.getId());
            imageupload.setIsDelete(false);
            d.Insert(imageupload);
            ID++;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    private static BufferedImage ToBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }
        image = new ImageIcon(image).getImage();
        boolean hasAlpha = HasAlpha(image);
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            int transparency = Transparency.OPAQUE;
            if (hasAlpha == true) {
                transparency = Transparency.BITMASK;
            }
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
        } catch (HeadlessException e) {
        }
        if (bimage == null) {
            int type = BufferedImage.TYPE_INT_RGB;
            if (hasAlpha == true) {
                type = BufferedImage.TYPE_INT_ARGB;
            }
            bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
        }
        Graphics g = bimage.createGraphics();
        g.drawImage(image, 0, 0, null);
        g.dispose();

        return bimage;
    }

    private static boolean HasAlpha(Image image) {
        if (image instanceof BufferedImage) {
            return ((BufferedImage) image).getColorModel().hasAlpha();
        }
        PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
        try {
            pg.grabPixels();
        } catch (InterruptedException e) {
        }
        return pg.getColorModel().hasAlpha();
    }

    private void DeleteAlbum(int indexAlbum) {
        Album album = albums.get(indexAlbum);
        albums.remove(indexAlbum);
        d.DeleteAlbum(album);
    }
}
